package com.gitee.wsl.compose.viewmodel

import androidx.compose.runtime.Composable
import androidx.compose.runtime.CompositionLocalProvider
import androidx.compose.runtime.DisposableEffect
import androidx.compose.runtime.key
import androidx.compose.runtime.remember
import androidx.lifecycle.ViewModelStore
import androidx.lifecycle.ViewModelStoreOwner
import androidx.lifecycle.viewmodel.compose.LocalViewModelStoreOwner

/**
 * ViewModelStore范围
 * 在某些情况下，在更可组合的函数范围级别管理 ViewModel 生命周期比 Activity 或 Jetpack Navigation 等更广泛的范围更可取。
 * 例如，您可能需要为底部工作表、LazyColumn 中的对话框或其他复杂的界面组件分配专用的 ViewModel
 * 实例，以防止在不同范围内意外重复使用相同的 ViewModel。
 * 这确保了更好的隔离和状态管理，特别是在 UI 元素需要独立生命周期处理的情况下。
 *
 * 考虑以下场景：您有一个项目列表，单击一个项目将打开特定于该项目的对话框。
 * 最初，一切似乎都正常。但是，如果您单击另一个项目，您会注意到，无论对话框被关闭多少次，
 * 相同的 ViewModel 实例正在被重复使用。
 * 这可能会导致不同对话中出现意外的状态持久性，从而影响预期行为。
 *
 * A disposable side-effect that creates a new [ViewModelStore] and [ViewModelStoreOwner],
 * scoping view models to a local store and ensuring the store is cleared when the it leaves the composition.
 *
 * @param key The key used to identify the store. The scope of the store will be decided by this key .
 * @param content The content of the composable.
 */
@Composable
public fun ViewModelStoreScope(
    key: Any,
    content: @Composable () -> Unit,
) {
    // Restart composition on every new instance of the factory
    key(key) {
        /** scope view models to a local store and reset the store with the given [key] */
        val viewModelStore = remember { ViewModelStore() }
        val viewModelStoreOwner = remember(viewModelStore) {
            object : ViewModelStoreOwner {
                override val viewModelStore: ViewModelStore get() = viewModelStore
            }
        }

        // Ensure the store is cleared when the composable is disposed
        DisposableEffect(Unit) {
            onDispose {
                viewModelStore.clear()
            }
        }

        CompositionLocalProvider(LocalViewModelStoreOwner provides viewModelStoreOwner) {
            content.invoke()
        }
    }
}
